<template>
  <edit-card title="创建任务" :confirm-text="'创建'" :loading="cardLoading" :type="'add'" @confirm="submit">
    <a-anchor
      style="position: absolute; top: 16px; right: 16px; width: 108px"
      :items="[
        { key: '1', href: '#components-anchor-demo-basic', title: '创建任务' },
        { key: '2', href: '#components-anchor-demo-static', title: '资源分配' }
      ]"
      wrapper-class="a-anchor-class"
      :target-offset="500"
      :offset-top="80 + 54"
      @click.prevent
    />
    <div id="components-anchor-demo-basic"></div>
    <a-form ref="mainFormRef" :colon="false" :model="mainForm" style="width: 824px" :rules="mainFormRules" name="mainForm">
      <a-form-item label="任务名称" name="name">
        <a-input v-model:value="mainForm.name" v-trim class="w-440" placeholder="请输入任务名称" :maxlength="200" />
      </a-form-item>
      <a-form-item label="任务类型" name="typeId">
        <a-select v-model:value="mainForm.typeId" class="w-440" :options="taskTypeList" @change="onSelectChange" />
      </a-form-item>
      <a-form-item label="选择模型" name="modelName">
        <a-select v-model:value="mainForm.modelName" class="w-440" :options="modelSelectOptions" />
      </a-form-item>
      <a-form-item label="运行参数" name="runParameters">
        <div>
          <a-space v-for="(param, index) in mainForm.runParameters" :key="index" style="display: flex; gap: 12px" align="baseline">
            <a-form-item
              :name="['runParameters', index, 'name']"
              :rules="{
                required: true,
                message: '请输入参数'
              }"
              class="w-215"
            >
              <a-input v-model:value="param.name" v-trim :disabled="!param.canDelete" placeholder="请输入参数" />
            </a-form-item>
            <a-form-item
              :name="['runParameters', index, 'value']"
              :rules="{
                required: true,
                message: '请输入值'
              }"
              class="w-215"
            >
              <a-input v-model:value="param.value" v-trim placeholder="请输入值" />
            </a-form-item>
            <MinusCircleOutlined v-if="param.canDelete" style="color: #cccdcf" title="删除" @click="removeParamInput(param)" />
          </a-space>
          <!-- <a-form-item>
            <a-button type="dashed" block class="w-440" @click="addRunParam">
              <PlusOutlined />
              <span style="color: rgba(17, 22, 31, 0.75)">添加</span>
            </a-button>
          </a-form-item> -->
        </div>
      </a-form-item>

      <a-form-item label="训练集" :name="mainForm.typeId === 1 ? 'dataNames' : 'radioValue'">
        <div class="training-set-tree-box">
          <a-tree
            v-if="mainForm.typeId === 1"
            ref="trainingSetTreeRef"
            v-model:expanded-keys="expandedKeys"
            v-model:checkedKeys="mainForm.dataNames"
            checkable
            :tree-data="trainingSetOptions"
            @check="onTreeSelect"
          />
          <a-tree
            v-else-if="mainForm.typeId === 2"
            ref="trainingSetTreeRef"
            v-model:expanded-keys="expandedKeys"
            :tree-data="trainingSetOptions"
          >
            <template #title="{ key, title }">
              <span v-if="key.startsWith('d-')">{{ title }} </span>
              <div v-else @click="radioValue = key">
                <a-radio :checked="radioValue === key" :value="key">{{ title }}</a-radio>
              </div>
            </template>
          </a-tree>
        </div>
      </a-form-item>
    </a-form>

    <div id="components-anchor-demo-static" class="default-class-title">资源分配</div>
    <a-form ref="resourceRef" :model="resourceForm" :colon="false" :rules="resourceRules" name="resourceForm">
      <a-form-item label="内存限制" name="memory">
        <div class="a-input-number">
          <a-input-number
            v-model:value="resourceForm.memory"
            :max="1000"
            placeholder="请输入"
            style="width: 104px"
            :maxlength="20"
            :min="1"
            :precision="0"
          />
          <span>GB</span>
        </div>
      </a-form-item>
      <a-form-item label="CPU限制" name="cpu">
        <div class="a-input-number">
          <a-input-number
            v-model:value="resourceForm.cpu"
            :max="1000"
            placeholder="请输入"
            style="width: 104px"
            :precision="0"
            :maxlength="20"
            :min="1"
          />
          <span>Core</span>
        </div>
      </a-form-item>

      <a-form-item label="显存限制" name="gpu">
        <div class="a-input-number">
          <a-input-number
            v-model:value="resourceForm.gpu"
            :max="1000"
            placeholder="请输入"
            style="width: 104px"
            :precision="0"
            :maxlength="20"
            :min="0"
          />
          <span>GB</span>
        </div>
      </a-form-item>
    </a-form>
  </edit-card>
</template>
<script lang="ts" setup>
  import type { SelectProps, TreeProps } from 'ant-design-vue'
  import { Modal } from 'ant-design-vue'
  import { Tree } from 'ant-design-vue'
  import type { Rule } from 'ant-design-vue/es/form'
  import { cloneDeep, regex, validateBitLen } from 'g6-fn'
  import { ref } from 'vue'
  import { watch } from 'vue'
  import { useRequest } from 'vue-request'
  import { useRouter } from 'vue-router'

  import { modelTrainingApi } from '@/services/api'

  import { taskTypeList } from '../options'
  import { getTaskTypeOptions } from '../utils'

  let router = useRouter()

  /* 资源分配逻辑-------------------------------------------------------------------------- */
  let resourceForm = ref({
    memory: 4,
    cpu: 4,
    gpu: 4
  })
  let resourceRef = ref()
  const resourceRules: Record<string, Rule[]> = {
    memory: [{ required: true, message: '请输入内存限制' }],
    cpu: [{ required: true, message: '请输入CPU限制' }],
    gpu: [{ required: true, message: '请输入GPU限制' }]
  }

  /* 任务表单逻辑---------------------------------------------------------------------------------- */
  interface AddInputType {
    name: string
    value: any
    canDelete: boolean
    uid?: number
  }
  interface MainForm {
    name: string
    typeId: number
    modelName: string
    dataNames: string[]
    runParameters: AddInputType[]
  }

  let mainForm = ref<MainForm>({
    name: '',
    typeId: 1,
    modelName: '',
    dataNames: [],
    runParameters: []
  })
  let mainFormRef = ref()
  const mainFormRules: Record<string, Rule[]> = {
    name: [
      { required: true, message: '请输入任务名称' },
      { validator: validateBitLen(200) },
      { pattern: regex.dirName, message: '名称不能包含\\ / : * ? " < > |', trigger: 'change' }
    ],
    runCommand: [{ required: true, message: '请输入运行命令' }],
    dataNames: [{ required: true, message: '请选择训练集' }],
    typeId: [{ required: true, message: '请选择任务类型' }],
    runParameters: [{ required: true, message: '请输入运行参数' }],
    modelName: [{ required: true, message: '请选择模型' }]
  }

  // 模型下拉选项
  const modelSelectOptions = ref<SelectProps['options']>([])
  const trainingSetOptions = ref<TreeProps['treeData']>([])
  const trainingSetTreeRef = ref<InstanceType<typeof Tree>>()
  const expandedKeys = ref<any[]>([])

  watch(
    () => mainForm.value.typeId,
    val => {
      setOptions(val)
    },
    { immediate: true }
  )

  /**
   * 设置模型选项、训练集选项、内置运行参数
   */
  function setOptions(taskType: number) {
    const options = getTaskTypeOptions(taskType)
    console.log('options', options)

    // 设置模型选项
    modelSelectOptions.value = options!.modelList.map(item => ({ label: item, value: item }))
    mainForm.value.modelName = modelSelectOptions.value[0].value as string

    //设置训练集内置参数
    mainForm.value.runParameters = []
    options!.paramList.forEach(item => {
      mainForm.value.runParameters.push({
        name: item.key,
        value: item.value,
        canDelete: false
      })
    })

    // 设置训练集
    trainingSetOptions.value = options!.trainingSet
    console.log(1111, trainingSetOptions.value)

    expandedKeys.value = trainingSetOptions.value.map(item => item.key)

    if (taskType === 1) {
      mainForm.value.dataNames = []
    } else {
      radioValue.value = trainingSetOptions.value[0].key as string
    }
  }

  /**
   * 增加运行参数
   */
  // const addRunParam = () => {
  //   if (mainForm.value.runParameters.length > 10) {
  //     return message.warning('最多只能添加十条')
  //   }
  //   mainForm.value.runParameters.push({
  //     name: '',
  //     value: '',
  //     canDelete: true,
  //     uid: Date.now()
  //   })
  // }

  /**
   * 删除运行参数
   */
  const removeParamInput = (param: AddInputType) => {
    mainForm.value.runParameters = mainForm.value.runParameters.filter(item => item.uid !== param.uid)
  }

  /* 图像检测单选-------------------------------------------------------------------------- */
  const radioValue = ref('')

  /* 整体逻辑-------------------------------------------------------------------------- */
  const { loading: cardLoading, runAsync: addTraining } = useRequest<ResponseData<void>>(modelTrainingApi.add)

  const submit = async () => {
    await mainFormRef.value?.validate()
    await resourceRef.value?.validate()
    await addTraining(formatParams(), { isAddUid: true })
    Modal.success({
      centered: true,
      content: '任务提交成功，请返回列表等待',
      okButtonProps: {
        type: 'default'
      },
      onOk: () => {
        router.back()
      }
    })
  }

  /* dataNames校验 */
  const onTreeSelect = () => {
    mainFormRef.value?.validate('dataNames')
  }
  const onSelectChange = () => {
    mainFormRef.value?.clearValidate('dataNames')
  }

  /**
   * 格式化运行参数
   */
  const formatParams = () => {
    let copyResource = cloneDeep(mainForm.value) as MainForm
    copyResource.runParameters.map((item: AddInputType) => {
      delete item.uid
      return item
    })
    let obj = {
      ...resourceForm.value,
      ...copyResource
    }

    console.log('obj', obj)
    if (copyResource.typeId === 1) {
      obj.dataNames = obj.dataNames.filter(item => !item.startsWith('d-'))
    } else if (copyResource.typeId === 2) {
      obj.dataNames = [radioValue.value]
    }

    return obj
  }
</script>

<style lang="less" scoped>
  .w-440 {
    width: 440px;
  }

  .a-input-number {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  :deep(.ant-form-item) {
    margin-bottom: 40px;

    .ant-form-item-label > label {
      width: 120px;
    }
  }

  .default-class-title {
    .font20b();

    position: relative;
    margin-bottom: 50px;
    // margin-left: 16px;

    &::before {
      position: absolute;
      top: 50%;
      left: -16px;
      width: 3px;
      height: 22px;
      background: #1868e9;
      border-radius: 0 2px 2px 0;
      content: '';
      transform: translateY(-50%);
      flex: none;
      order: 0;
      align-self: stretch;
      flex-grow: 0;
    }
  }

  .a-anchor-class {
    position: absolute !important;
    top: 54px;
    right: 10;
  }

  .training-set-tree-box {
    overflow: auto;
    padding: 8px 12px;
    width: 440px;
    height: 400px;
    border: 1px solid #d9d9db;
    border-radius: 6px;
  }
</style>
